library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

-- not really sub, since for negative denominators, we will "add" instead of subtract
-- pure combinatorial
entity div_sub_and_select is

	PORT (
		
		times1 : in STD_LOGIC_VECTOR(34 downto 0);
		times2 : in STD_LOGIC_VECTOR(34 downto 0);
		times3 : in STD_LOGIC_VECTOR(34 downto 0);
		
		feedback_in : in STD_LOGIC_VECTOR(31 downto 0);
		
		is_signed : in STD_LOGIC; 
		
		out_diff : out STD_LOGIC_VECTOR(31 downto 0);
		quotient_digit : out STD_LOGIC_VECTOR(1 downto 0)
	
	);
	
end div_sub_and_select;

architecture Behavioral of div_sub_and_select is

begin
	process(times1, times2, times3, feedback_in, is_signed)
		variable processed_change1 : STD_LOGIC_VECTOR(34 downto 0);
		variable processed_change2 : STD_LOGIC_VECTOR(34 downto 0);
		variable processed_change3 : STD_LOGIC_VECTOR(34 downto 0);
		
		variable invert : STD_LOGIC_VECTOR(0 downto 0);
		
		variable sub_result1 : STD_LOGIC_VECTOR(34 downto 0);
		variable sub_result2 : STD_LOGIC_VECTOR(34 downto 0);
		variable sub_result3 : STD_LOGIC_VECTOR(34 downto 0);
		
	begin
		invert(0) := not (is_signed and times1(34)); -- we invert whenever it is unsigned OR the denominator is positive
		processed_change1 := times1 xor (34 downto 0 => (invert(0)));
		processed_change2 := times2 xor (34 downto 0 => (invert(0)));
		processed_change3 := times3 xor (34 downto 0 => (invert(0)));
		
		--- send into one adder each
		sub_result1 := STD_LOGIC_VECTOR(unsigned(feedback_in) + unsigned(processed_change1) + unsigned(invert));
		sub_result2 := STD_LOGIC_VECTOR(unsigned(feedback_in) + unsigned(processed_change2) + unsigned(invert));
		sub_result3 := STD_LOGIC_VECTOR(unsigned(feedback_in) + unsigned(processed_change3) + unsigned(invert));
		
		if (sub_result3(34) = '0') then
			out_diff <= sub_result3(31 downto 0);
			quotient_digit <= "11";
		elsif (sub_result2(34) = '0') then
			out_diff <= sub_result2(31 downto 0);
			quotient_digit <= "10";
		elsif (sub_result1(34) = '0') then
			out_diff <= sub_result1(31 downto 0);
			quotient_digit <= "01";
		else
			out_diff <= feedback_in;
			quotient_digit <= "00";
		end if;
		
	end process;

end Behavioral;

